package com.czkt.config;

import com.czkt.pojo.SysRight;
import com.czkt.service.ISysRightService;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * shiro相关配置
 * 1、定义域
 * 2、定义securityManager
 * 3、过滤器   提前告诉shiro 我使用规则
 */
@Configuration
public class ShiroConfig {


    /**
     * 加密方式
     * @return
     */
    @Bean
    public CredentialsMatcher getHashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //加密算法名称
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //加密次数
        hashedCredentialsMatcher.setHashIterations(2);

        return hashedCredentialsMatcher;
    }

    /**
     * 将自定义域交给spring管理
     *
     * @return
     */
    @Bean
    public Realm getRealm() {
        CustomRealm realm = new CustomRealm();

//        realm.setCachingEnabled(true);
        //设置域开启授权缓存
        realm.setAuthorizationCachingEnabled(true);

//        realm.setAuthenticationCachingEnabled(true);

//        realm.setAuthenticationCacheName("authenticationCacheName");
        realm.setAuthorizationCacheName("authorizationCacheName");

        //设置加密方式
        realm.setCredentialsMatcher(getHashedCredentialsMatcher());
        return realm;
    }

    @Value("${spring.redis.password}")
    String redisPwd;


    public RedisManager getRedisManager(){
        RedisManager redisManager = new RedisManager();
        redisManager.setPassword(redisPwd);

        return redisManager;
    }

//    @Bean
   public RedisCacheManager getCacheManager(){
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(getRedisManager());
        //设置shiro中的标识属性
       redisCacheManager.setPrincipalIdFieldName("usrId");
        return redisCacheManager;
    }


   public RedisSessionDAO  getRedisSessionDao(){
       RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
       redisSessionDAO.setRedisManager(getRedisManager());
       return redisSessionDAO;
    }

    public DefaultWebSessionManager getDefaultWebSessionManager(){
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        defaultWebSessionManager.setSessionDAO(getRedisSessionDao());
        //URL不显示sessionId
        defaultWebSessionManager.setSessionIdUrlRewritingEnabled(false);
        return  defaultWebSessionManager;
    }



    /**
     * 将自定义域注入到securityManager 用于后续认证授权数据对比
     *
     * @return
     */
    @Bean
    public SecurityManager getSecurityManager() {
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager(getRealm());
        defaultSecurityManager.setCacheManager(getCacheManager());
        defaultSecurityManager.setSessionManager(getDefaultWebSessionManager());


        return defaultSecurityManager;
    }

    @Autowired
    ISysRightService sysRightService;

    /**
     * 将sercurityManager注入shiro过滤器，用于后续的认证授权等功能
     *
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(getSecurityManager());


        //配置资源认证规则
        Map<String, String> urlMap = new LinkedHashMap<>();
        urlMap.put("/css/*", "anon");
        urlMap.put("/js/*", "anon");
        urlMap.put("/fonts/*", "anon");
        urlMap.put("/images/*", "anon");
        urlMap.put("/localcss/*", "anon");
        urlMap.put("/localjs/*", "anon");

        urlMap.put("/doLogin", "anon");

        urlMap.put("/logout", "anon");

//        登录页面
        urlMap.put("/", "anon");


        //从数据库获取 动态

        List<SysRight> rightList = sysRightService.list();
        for (SysRight sysRight : rightList) {
            if (StringUtils.hasText(sysRight.getRightUrl())) {
                urlMap.put(sysRight.getRightUrl(), "perms[" + sysRight.getRightCode() + "]");
            }
        }


        //除了上面配置的路径的规则其它请求必须认证通过才可访问
        urlMap.put("/**", "authc");
        filterFactoryBean.setFilterChainDefinitionMap(urlMap);


        filterFactoryBean.setLoginUrl("/");
        //设置权限不足页面
        filterFactoryBean.setUnauthorizedUrl("/403");

        return filterFactoryBean;
    }


}
